<!-- views/MainPage.vue -->
<template>
  <div class="container">
    <div class="row1">
      <SystemHeader />
    </div>

    <!----------------------------------------- 左侧布局 --------------------------------------------------->
    <div class="row2">
      <div class="row2-column1">
        <!-- row2上方 -->
        <div class="row2-column1-row1">
          <!-- 显示主摄像头图像 -->
          <div class="card1">
            <div class="card-header">
              <span>摄像头实时监控画面 </span>
              <select v-model="cameraId" @change="switchCamera" class="camera-select">
                <option v-for="id in cameraOptions" :key="id" :value="id">摄像头 {{ id }}</option>
              </select>
            </div>
            <CameraView :video-frame="currentVideoFrame" />
          </div>
          <!-- 显示主摄像头图像 -->

          <!-- 显示3D重构图像 -->
          <div class="card1">
            <div class="card-header">三维重构画面</div>
            <VirtualScene :scene-frame="current3DFrame" />
          </div>
          <!-- 显示3D重构图像 -->
        </div>
        <!-- row2上方 -->

        <!-- row2下方 -->
        <div class="row2-column1-row2">
          <div class="card2">
            <div class="card-header">视觉场景理解 >> 语义场景图构建</div>
            <div class="card3">
              <div class="card4l">
                <CameraAndTextPanel
                  :camera-image-url="cameraImageUrl"
                  :image-understanding-result="imageUnderstandingResult"
                />
              </div>
              <div class="card4m">
                <Arrow :arrow-icon="arrowIcon" />
              </div>
              <div class="card4r">
                <SceneGraphPanel :graph-data="sceneGraphData" />
              </div>
            </div>
          </div>
        </div>
        <!-- row2下方 -->
      </div>
      <!----------------------------------------- 左侧布局 --------------------------------------------------->

      <!----------------------------------------- 右侧布局 --------------------------------------------------->
      <div class="row2-column2-ai-chat">
        <div class="card-header">AI交互窗口</div>
        <AIChat @send="sendMessage" @reset="resetSceneGraph" ref="AIChatRef" />
      </div>
      <!----------------------------------------- 右侧布局 --------------------------------------------------->
    </div>
  </div>
</template>

<!---------------------------------------------------------------- CSS样式 ---------------------------------------------------------------->
<style scoped>
/* 禁止页面滚动 */
html,
body {
  overflow: hidden;
  height: 100%;
  margin: 0;
  padding: 0;
  background-color: #ffffff;
  color: #333333;
}

/* 容器样式 */
.container {
  display: flex;
  flex-direction: column;
  height: 100%;
  /* weight: 100%; */
  background-color: #ffffff; /* 深色背景 #1f2a44*/
  overflow: hidden;
}
/* 第一行 */
.row1 {
  flex: 0 1 auto;
  display: flex;
  /* width: max-content; */
  flex-direction: column;
  padding-top: 0.8%;
  gap: 0px;
}

/* 第二行 */
.row2 {
  display: flex;
  flex: 1 1 auto;
  flex-direction: row;
  justify-content: space-between;
  padding-top: 10px;
  gap: 0px;
}
/* 卡片头部 */
.card-header {
  padding: 8px 15px;
  background: linear-gradient(90deg, #00c4b4, #4682b4);
  background: #3773e1;
  color: #ffffff;
  font-size: 16px;
  font-weight: bold;
}

/* 第二行左侧 */
.row2-column1 {
  flex: 0 0 75%;
  width: 75%;
  display: flex;
  justify-content: flex-start;
  flex-direction: column;
  padding-top: 0px;
  gap: 0px;
}

/* 第二行左侧的上方 */
.row2-column1-row1 {
  display: flex;
  flex: 1 1 auto;
  flex-direction: row;
  flex-wrap: nowrap;
  padding-top: 0px;
  align-items: stretch;
  justify-content: space-between;
}
.card1 {
  display: flex;
  flex-direction: column;
  flex: 0 1 49.6%;
  border-radius: 8px 8px 8px 8px;
  background-color: #ffffff;
  overflow: hidden;
  box-shadow: none;
  transition:
    transform 0.3s ease,
    box-shadow 0.3s ease;
  animation: fadeInUp 0.5s ease;
}
/* 摄像头选择按钮 */
.camera-select {
  padding-left: 5px;
  border: 1px solid #a6a6a6;
  border-radius: 4px;
  background-color: #fff;
  font-size: 12px;
  font-weight: bold;
  color: #333;
  cursor: pointer;
  transition: border-color 0.3s ease;
}
.camera-select:hover {
  border-color: #a0a0a0;
}
.camera-select:focus {
  outline: none;
  border-color: #007bff !important;
  box-shadow: 0 0 3px rgba(0, 123, 255, 0.5);
}

/* 第二行左侧下方 */
.row2-column1-row2 {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  flex-wrap: nowrap;
  padding-top: 0.8%;
  justify-content: flex-start;
  height: 54%;
  align-items: stretch;
}
.card2 {
  display: flex;
  flex: 1 1 100%;
  flex-direction: column;
  flex-wrap: nowrap;
  align-items: stretch;

  border-radius: 8px;
  background-color: #ffffff;
  overflow: hidden;
  transition:
    transform 0.3s ease,
    box-shadow 0.3s ease;
  animation: fadeInUp 0.5s ease;
}
.card3 {
  display: flex;
  flex: 1 1 100%;
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: space-evenly;
  align-items: center;

  border-radius: 0px 0px 8px 8px;
  border-left: 1.5px solid #a6a6a6;
  border-right: 1.5px solid #a6a6a6;
  border-bottom: 1.5px solid #a6a6a6;
  background-color: #ffffff; /* #f2f2f2 */
  overflow: hidden;
  transition:
    transform 0.3s ease,
    box-shadow 0.3s ease;
  animation: fadeInUp 0.5s ease;
}
.card4l {
  display: flex;
  flex: 0 1 40%;
  height: 43vh;
  flex-direction: column;
  flex-wrap: nowrap;
  border-radius: 6px 6px 6px 6px;
  border: 1px solid #d6d6d6;
  /* box-shadow:  3px 3px rgba(0, 0, 0, 0.05); */
  background-color: #ffffff;
  overflow: hidden;
  transition:
    transform 0.3s ease,
    box-shadow 0.3s ease;
  animation: fadeInUp 0.5s ease;
}
.card4m {
  display: flex;
  flex: 0 1 8%;
  flex-direction: column;
  flex-wrap: nowrap;
  border-radius: 0px;
  background-color: #ffffff;
  overflow: hidden;
  transition:
    transform 0.3s ease,
    box-shadow 0.3s ease;
  animation: fadeInUp 0.5s ease;
}

.card4r {
  display: flex;
  flex: 0 1 40%;
  height: 43vh;
  flex-direction: column;
  flex-wrap: nowrap;
  /* align-items: stretch; */

  border-radius: 6px;
  border: 1px solid #d6d6d6;
  background-color: #ffffff;
  overflow: hidden;
  transition:
    transform 0.3s ease,
    box-shadow 0.3s ease;
  animation: fadeInUp 0.5s ease;
}

/* 第二行第二列AI聊天窗口 */
.row2-column2-ai-chat {
  flex: 1 1 24.2%;
  display: flex;
  flex-direction: column;
  padding-top: 0px;
  margin-left: 0.8%;
  border-radius: 8px;
  overflow: hidden;
  transition:
    transform 0.3s ease,
    box-shadow 0.3s ease;
}
</style>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import SystemHeader from '@/components/layout/SystemHeader.vue'
import CameraView from '@/components/modules/CameraView.vue'
import VirtualScene from '@/components/modules/VirtualScene.vue'
import SceneGraphPanel from '@/components/modules/SceneGraphPanel.vue'
import CameraAndTextPanel from '@/components/modules/CameraAndTextPanel.vue'
// import InputPanel from '@/components/layout/InputPanel.vue'
import AIChat from '@/components/modules/AIChat.vue'
import Arrow from '@/components/modules/Arrow.vue'
const AIChatRef = ref(null)

// 响应式变量
const currentVideoFrame = ref('/images/init1.png') // 当前视频帧
const current3DFrame = ref('/images/init2.png') // 当前 3D 场景帧
const arrowIcon = ref('/images/arrow3.png')
const message = ref('') // 用户输入的文本
const cameraImageUrl = ref() // 摄像头画面 URL
const imageUnderstandingResult = ref('') // 图像理解结果
const cameraId = ref(2) // 默认摄像头 ID
const cameraOptions = ref([0, 1, 2, 3, 4, 5, 6, 7]) // 可用的摄像头 ID 列表
const commandData = ref('') //3D指令信息

let URI_CAMERA = 'ws://10.195.233.11:61310'
let URI_SceneGraph = 'ws://10.195.233.11:61311'
let URI_3D_COMMAND = 'ws://10.195.233.11:61312/getAll'

let URI_CommandScene = 'ws://127.0.0.1:8080/command'
let URI_SceneFrame = 'ws://127.0.0.1:8080/frame'

const sceneGraphData = ref({
  nodes: [],
  edges: [],
})

let videoWebSocket = null // 用于视频帧和 3D 场景帧的 WebSocket 实例
let queryWebSocket = null // 用于视觉理解的 WebSocket 实例
let commandWebSocket = null //用于3D信息的 WebSocket 实例

let commandSceneWebSocket = null // 用于发送指令到 3D 端
let frameSceneWebSocket = null // 用于接收 3D 端的图像帧

let commandInterval = null

// 初始化视频帧连接
const initVideoWebSocket = () => {
  videoWebSocket = new WebSocket(URI_CAMERA) // 与后端匹配

  videoWebSocket.binaryType = 'arraybuffer' // 设置为接收 ArrayBuffer 数据

  // 监听连接成功
  videoWebSocket.onopen = () => {
    console.log('视频帧 WebSocket 连接成功')
    // 连接成功后发送摄像头 ID（例如 2）
    videoWebSocket.send(cameraId.value.toString()) // 根据需要修改摄像头 ID
  }

  // 监听服务器消息
  videoWebSocket.onmessage = (event) => {
    // 接收到的数据是 JPG 二进制格式
    const byteArray = new Uint8Array(event.data)
    const blob = new Blob([byteArray], { type: 'image/jpeg' })
    const url = URL.createObjectURL(blob)

    // 更新视频帧
    if (currentVideoFrame.value) {
      URL.revokeObjectURL(currentVideoFrame.value) // 释放旧的 URL
    }
    currentVideoFrame.value = url

    // 请求下一帧（保持实时性）
    // 控制帧率，每 33ms 请求一帧
    setTimeout(() => {
      if (videoWebSocket.readyState === WebSocket.OPEN) {
        videoWebSocket.send(cameraId.value.toString())
      }
    }, 33)
  }

  // 监听连接关闭
  videoWebSocket.onclose = () => {
    console.log('视频帧 WebSocket 连接关闭')
    // 自动重连
    setTimeout(initVideoWebSocket, 1000)
  }

  // 监听连接错误
  videoWebSocket.onerror = (error) => {
    console.error('视频帧 WebSocket 错误:', error)
  }
}

// 切换摄像头
const switchCamera = () => {
  if (videoWebSocket && videoWebSocket.readyState === WebSocket.OPEN) {
    videoWebSocket.send(cameraId.value.toString())
    console.log(`切换到摄像头 ${cameraId.value}`)
  }
}

// 3D命令 WebSocket
const initCommandWebSocket = () => {
  commandWebSocket = new WebSocket(URI_3D_COMMAND)

  commandWebSocket.onopen = () => {
    console.log('命令 WebSocket 连接成功')
    // commandWebSocket.send('getAll')
    // 持续发送getAll请求
    commandInterval = setInterval(() => {
      if (commandWebSocket.readyState === WebSocket.OPEN) {
        commandWebSocket.send('getAll')
        // console.log('定期发送 getAll 请求')
      }
    }, 100) // 每 0.5 秒发送一次
  }

  commandWebSocket.onmessage = (event) => {
    commandData.value = event.data
    requestSceneFrame() // 直接将服务端数据发送给 3D 端
  }

  commandWebSocket.onclose = () => {
    console.log('命令 WebSocket 连接关闭')
    clearInterval(commandInterval)
    setTimeout(initCommandWebSocket, 1000)
  }

  commandWebSocket.onerror = (error) => {
    console.error('命令 WebSocket 错误:', error)
    commandData.value = '连接错误，请检查服务'
  }
}

// 初始化发送指令的 WebSocket
const initCommandSceneWebSocket = () => {
  commandSceneWebSocket = new WebSocket(URI_CommandScene) // 连接到 /command 端点

  commandSceneWebSocket.onopen = () => {
    console.log('3D 指令 WebSocket 连接成功')
  }
  commandSceneWebSocket.onclose = () => {
    console.log('3D 指令 WebSocket 连接关闭')
    setTimeout(initCommandSceneWebSocket, 1000) // 自动重连，增加 1 秒延迟
  }
  commandSceneWebSocket.onerror = (error) => {
    console.error('3D 指令 WebSocket 错误:', error)
  }
}

// 初始化接收帧的 WebSocket
const initFrameSceneWebSocket = () => {
  frameSceneWebSocket = new WebSocket(URI_SceneFrame) // 连接到 /frame 端点

  frameSceneWebSocket.binaryType = 'arraybuffer' // 接收二进制图像数据

  frameSceneWebSocket.onopen = () => {
    console.log('3D 帧 WebSocket 连接成功')
    // 连接成功后立即发送一个任意消息以请求第一帧
    frameSceneWebSocket.send('request_frame')
  }

  frameSceneWebSocket.onmessage = (event) => {
    const byteArray = new Uint8Array(event.data)
    const blob = new Blob([byteArray], { type: 'image/jpeg' })
    const url = URL.createObjectURL(blob)
    if (current3DFrame.value) {
      URL.revokeObjectURL(current3DFrame.value) // 释放旧 URL，避免内存泄漏
    }
    current3DFrame.value = url
    // console.log('收到 3D 端图像帧')

    // 收到帧后立即发送消息请求下一帧
    if (frameSceneWebSocket.readyState === WebSocket.OPEN) {
      frameSceneWebSocket.send('request_frame') // 再次发送消息以保持帧流
    }
  }

  frameSceneWebSocket.onclose = () => {
    console.log('3D 帧 WebSocket 连接关闭')
    setTimeout(initFrameSceneWebSocket, 1000) // 自动重连，增加 1 秒延迟
  }

  frameSceneWebSocket.onerror = (error) => {
    console.error('3D 帧 WebSocket 错误:', error)
  }
}

// 请求 3D 场景数据
const requestSceneFrame = () => {
  if (commandSceneWebSocket && commandSceneWebSocket.readyState === WebSocket.OPEN) {
    if (commandData.value) {
      // 解析 JSON 字符串
      const parsedData = JSON.parse(commandData.value)
      //发送 commandData
      commandSceneWebSocket.send(commandData.value) // 通过 /command 发送指令
    } else {
      console.log('未收到服务端指令，暂不发送给 3D 端')
    }
  } else {
    // console.log('3D WebSocket 未连接，无法发送指令')
  }
}

// 初始化 场景图服务 WebSocket连接
const initQueryWebSocket = () => {
  queryWebSocket = new WebSocket(URI_SceneGraph)

  // 监听连接成功
  queryWebSocket.onopen = () => {
    console.log('查询 WebSocket 连接成功')
  }

  // 监听服务器消息
  queryWebSocket.onmessage = (event) => {
    const response = JSON.parse(event.data)
    console.log('收到服务器响应:', response)

    // 更新界面数据
    cameraImageUrl.value = response.data.image_url // 显示摄像头画面
    if (response.data.answer) {
      AIChatRef.value.showMessage(response.data.answer, response.data.image_url)
    }
    imageUnderstandingResult.value = response.data.answer // 显示图像理解结果
    // 场景图数据更新（直接获取scene_graph）
    if (response.data.scene_graph) {
      // 检查数据存在性
      sceneGraphData.value = response.data.scene_graph
    } else {
      sceneGraphData.value = { error: '未获取到场景图数据' }
    }

  }

  // 监听连接关闭
  queryWebSocket.onclose = () => {
    console.log('查询 WebSocket 连接关闭')
    initQueryWebSocket() // 自动重连
  }

  // 监听连接错误
  queryWebSocket.onerror = (error) => {
    console.error('查询 WebSocket 错误:', error)
  }

}

// 发送查询
const sendMessage = (content) => {
  console.log('接收到输入框内容:', content)
  if (!content || !content.trim()) {
    alert('请输入有效的查询内容')
    return
  }
  if (queryWebSocket && queryWebSocket.readyState === WebSocket.OPEN) {
    const messageData = {
      query: content,
      reset: false, // 默认值为 false，后续可通过按钮修改
    }
    queryWebSocket.send(JSON.stringify(messageData))
    message.value = ''
  } else {
    console.error('查询 WebSocket 未连接')
  }
}

// 重置场景图
const resetSceneGraph = () => {
  if (queryWebSocket && queryWebSocket.readyState === WebSocket.OPEN) {
    const messageData = {
      query: '',
      reset: true,
    }
    queryWebSocket.send(JSON.stringify(messageData))
    console.log('发送重置请求')
  } else {
    console.error('查询 WebSocket 未连接')
    alert('无法重置场景图：WebSocket 未连接')
  }
}

onMounted(async () => {
  // 禁止页面滚动
  document.body.style.overflow = 'hidden'

  // 初始化视频帧和 3D 场景帧的 WebSocket 连接
  initVideoWebSocket()
  initCommandWebSocket()
  // initSceneWebSocket()
  initCommandSceneWebSocket() // 初始化发送指令的 WebSocket
  initFrameSceneWebSocket() // 初始化接收帧的 WebSocket
  // 初始化查询 WebSocket 连接
  initQueryWebSocket()
})

onUnmounted(() => {
  // 恢复页面滚动
  document.body.style.overflow = 'auto'

  // 关闭 WebSocket 连接
  if (videoWebSocket) {
    videoWebSocket.close()
  }
  if (commandWebSocket) {
    commandWebSocket.close()
    clearInterval(commandInterval) //清除定时器
  }

  if (commandSceneWebSocket) commandSceneWebSocket.close() // 关闭指令 WebSocket
  if (frameSceneWebSocket) frameSceneWebSocket.close() // 关闭帧 WebSocket
  if (queryWebSocket) {
    queryWebSocket.close()
  }
  if (currentVideoFrame.value) {
    URL.revokeObjectURL(currentVideoFrame.value)
  }
  if (current3DFrame.value) {
    URL.revokeObjectURL(current3DFrame.value)
  }
})
</script>
